/*
 * Created on 2006-3-15
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package  org.fantasy.common.util;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

import org.apache.commons.collections.FastHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Element;


/**
 * 将ResultSet数据集转为XML串
 * @author lrq
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class ResultSetToXML {	
	private static Log log = LogFactory.getLog(ResultSetToXML.class);
	
	private boolean trimBar;                                  //是否去掉“_”，去掉“_”后，将按照aaBbCc格式进行转换
	private boolean lowerCase;						          //列名是否小写，只有在trimBar=false才有用
	private int limit;								          //记录数限制		
	
	private Document xmlDoc;
	private String xmlString;
	private FastHashMap colMap;
	private String encoding;
	
	public ResultSetToXML(ResultSet resultSet, String encoding)throws SQLException,XMLDocException{
		this(resultSet, encoding, true, true, -1);
	}
	public ResultSetToXML(ResultSet resultSet, String encoding, int limit)throws SQLException,XMLDocException{
		this(resultSet, encoding, true, true, limit);
	}
	
	public ResultSetToXML(ResultSet resultSet, int limit)throws SQLException,XMLDocException{
		this(resultSet, XMLUtil.DEFAULT_ENCODING, true, true, limit);
	}
	

	/**
	 * @param resultSet
	 * @param encoding
	 * @param trimBar
	 * @param lowerCase
	 * @param limit
	 * @throws SQLException
	 * @throws XMLDocException
	 */
	public ResultSetToXML(ResultSet resultSet, String encoding, boolean trimBar, boolean lowerCase, int limit) 
		throws SQLException, XMLDocException{
	    if(resultSet == null) {
		    setXmlDoc(null);
		    return;
	    }	    
	    
	    this.trimBar = trimBar;
	    this.lowerCase = lowerCase;
        this.limit = limit;
        
        if(encoding==null || "".equals(encoding)) 
            this.encoding = XMLUtil.DEFAULT_ENCODING;
	    
	    colMap = new FastHashMap();
	    colMap.setFast(true);	    
	    
	    //xmlDoc = XMLUtil.fromXML("<?xml version=\"1.0\" encoding=\"" + this.encoding + "\"?>", this.encoding);
	    xmlDoc = XMLUtil.createDocument();
	    log.debug("begin introspect...");
        introspect(resultSet);     
        log.debug("begin convert...");
        convertToXMLDoc(resultSet);        
	}
	
	
	/**
	 * 解析列名，
	 * @param resultSet
	 * @throws SQLException
	 */
	protected void introspect(ResultSet resultSet)throws SQLException{	    
	    ResultSetMetaData metadata = resultSet.getMetaData();
	    
	    int n = metadata.getColumnCount();
	    String name = null;
	    for(int i = 1; i <= n; i++){	    	
		    if(lowerCase)
		        name = metadata.getColumnName(i).toLowerCase();
		    else
		        name = metadata.getColumnName(i);		    
		    name = StringUtil.getFieldString(name);	
		    log.debug("name:" + name);
		    colMap.put(metadata.getColumnName(i), name);
	    }	
	    
	}
	
	protected void convertToXMLDoc(ResultSet resultSet)throws SQLException{
		Element root = xmlDoc.addElement(Constants.XML_RESULT_ROOT);
		ResultSetMetaData metaData = resultSet.getMetaData();
		Element row;
		for(int cnt = 0; resultSet.next() && (limit < 0 || cnt < limit); cnt++)
        {
			row = XMLUtil.appendChild(root, Constants.XML_RESULT_ROW);
			row.addAttribute("OID",String.valueOf(cnt));        
			String colName;        
			for(int i=1; i<=metaData.getColumnCount(); i++){            
                colName = metaData.getColumnName(i);
                if(resultSet.getObject(colName)!=null)                	
                    XMLUtil.appendChild(row, (String)colMap.get(colName), resultSet.getObject(colName).toString());                	
                else
                	XMLUtil.appendChild(row, (String)colMap.get(colName), "");
			}   
        }
		
		/*StringBuffer sbuf = new StringBuffer(20000);
		ResultSetMetaData metaData = resultSet.getMetaData();
		sbuf.append("<?xml version=\"1.0\" encoding=\"" + this.encoding + "\"?>");
		for(int cnt = 0; resultSet.next() && (limit < 0 || cnt < limit); cnt++)
        {
			String colName;
			sbuf.append("<row>");
			for(int i=1; i<=metaData.getColumnCount(); i++){            
                colName = metaData.getColumnName(i);
                if(resultSet.getObject(colName)!=null){  
                	sbuf.append("<" + (String)colMap.get(colName) + ">");
                	sbuf.append(resultSet.getObject(colName).toString());
                	sbuf.append("</" + (String)colMap.get(colName) + ">");
                }
			}
			sbuf.append("</row>");
			//System.out.println(cnt);
        }
		this.xmlString = sbuf.toString(); */
	}

	
	/**
	 * @return Returns the xmlDoc.
	 */
	public Document getXmlDoc() {
		return xmlDoc;
	}
	/**
	 * @param xmlDoc The xmlDoc to set.
	 */
	public void setXmlDoc(Document xmlDoc) {
		this.xmlDoc = xmlDoc;
	}
	/**
	 * @return Returns the xmlString.
	 */
	public String getXmlString() {
		return xmlString;
	}
	/**
	 * @param xmlString The xmlString to set.
	 */
	public void setXmlString(String xmlString) {
		this.xmlString = xmlString;
	}
}
